"""扫雷游戏"""
import tkinter as tk
from tkinter import messagebox
import random


class Minesweeper:
    def __init__(self, master, rows=9, cols=9, mines_num=10):
        self.master = master
        self.rows = rows
        self.cols = cols
        self.mines_num = mines_num
        self.remaining_mines = mines_num
        self.game_over = False
        self.first_click = True

        # 初始化网格数据
        self.mines = set()
        self.flags = set()
        self.opened = set()
        self.grid = [[0 for _ in range(cols)] for _ in range(rows)]

        self.create_widgets()
        self.create_bindings()

    def create_widgets(self):
        # 创建顶部显示
        self.top_frame = tk.Frame(self.master)
        self.top_frame.pack()
        self.mine_label = tk.Label(self.top_frame, text=f"Mines: {self.remaining_mines}")
        self.mine_label.pack(side=tk.LEFT)

        # 创建重新开始按钮
        self.restart_btn = tk.Button(self.top_frame, text="Restart", command=self.restart)
        self.restart_btn.pack(side=tk.RIGHT)

        # 创建游戏网格
        self.frame = tk.Frame(self.master)
        self.frame.pack()

        self.buttons = []
        for i in range(self.rows):
            row = []
            for j in range(self.cols):
                btn = tk.Button(self.frame, width=2, height=1)
                btn.grid(row=i, column=j)
                btn.bind('<Button-1>', lambda e, i=i, j=j: self.left_click(i, j))
                btn.bind('<Button-3>', lambda e, i=i, j=j: self.right_click(i, j))
                row.append(btn)
            self.buttons.append(row)

    def create_bindings(self):
        self.master.bind('<r>', lambda e: self.restart())

    def restart(self):
        self.mines.clear()
        self.flags.clear()
        self.opened.clear()
        self.remaining_mines = self.mines_num
        self.game_over = False
        self.first_click = True
        self.mine_label.config(text=f"Mines: {self.remaining_mines}")

        # 重置按钮
        for i in range(self.rows):
            for j in range(self.cols):
                self.buttons[i][j].config(
                    text='',
                    bg='SystemButtonFace',
                    state=tk.NORMAL
                )
        self.generate_mines()  # 延迟生成雷区

    def generate_mines(self, exclude_i=-1, exclude_j=-1):
        # 生成排除首次点击位置的雷区
        all_cells = [(i, j) for i in range(self.rows) for j in range(self.cols)]
        if exclude_i != -1 and exclude_j != -1:
            all_cells.remove((exclude_i, exclude_j))
        self.mines = set(random.sample(all_cells, self.mines_num))

        # 计算周围雷数
        for i in range(self.rows):
            for j in range(self.cols):
                if (i, j) in self.mines:
                    continue
                count = 0
                for dx in [-1, 0, 1]:
                    for dy in [-1, 0, 1]:
                        if dx == 0 and dy == 0:
                            continue
                        x, y = i + dx, j + dy
                        if 0 <= x < self.rows and 0 <= y < self.cols:
                            if (x, y) in self.mines:
                                count += 1
                self.grid[i][j] = count

    def left_click(self, i, j):
        if self.game_over or (i, j) in self.flags:
            return

        if self.first_click:
            self.generate_mines(i, j)
            self.first_click = False

        if (i, j) in self.mines:
            self.buttons[i][j].config(text='*', bg='red')
            self.game_over = True
            self.reveal_mines()
            messagebox.showinfo("Game Over", "You hit a mine!")
            return

        self.open_cell(i, j)
        self.check_win()

    def right_click(self, i, j):
        if self.game_over or (i, j) in self.opened:
            return

        if (i, j) in self.flags:
            self.flags.remove((i, j))
            self.remaining_mines += 1
            self.buttons[i][j].config(text='')
        else:
            self.flags.add((i, j))
            self.remaining_mines -= 1
            self.buttons[i][j].config(text='🚩')

        self.mine_label.config(text=f"Mines: {self.remaining_mines}")
        self.check_win()

    def open_cell(self, i, j):
        if (i, j) in self.opened:
            return

        self.opened.add((i, j))
        self.buttons[i][j].config(
            state=tk.DISABLED,
            relief=tk.SUNKEN,
            bg='light gray'
        )

        if self.grid[i][j] > 0:
            self.buttons[i][j].config(text=str(self.grid[i][j]))
            return

        # 递归打开周围空白格
        for dx in [-1, 0, 1]:
            for dy in [-1, 0, 1]:
                x, y = i + dx, j + dy
                if 0 <= x < self.rows and 0 <= y < self.cols:
                    self.open_cell(x, y)

    def reveal_mines(self):
        for i, j in self.mines:
            self.buttons[i][j].config(text='*', bg='orange')

    def check_win(self):
        # 胜利条件：所有非雷格子都被打开
        if len(self.opened) + len(self.mines) == self.rows * self.cols:
            self.game_over = True
            messagebox.showinfo("Congratulations!", "You won!")
        # 或者所有雷都被正确标记
        elif self.flags == self.mines:
            self.game_over = True
            messagebox.showinfo("Congratulations!", "You won!")


if __name__ == "__main__":
    root = tk.Tk()
    root.title("Minesweeper")
    game = Minesweeper(root)
    root.mainloop()